#include "threadPool.h"
#define STR_LEN 8 //定义随机输出的字符串长度。
                  //用户注册函数
int signUp(int netfd, userInfo_t *user, MYSQL *mysql){
    ////根据用户注册函数的整个，一一接收
    train_t train;
    memset(&train, 0, sizeof(train));

    // 服务端 注册函数 第二次接收，接收账号、密码
    recv(netfd, &train.length, sizeof(int), MSG_WAITALL);
    recv(netfd, train.data, train.length, MSG_WAITALL);
    printf("%s\n", train.data);
    memcpy(user, train.data, train.length);
    //printf("userName = %s\n明文passWord = %s\n", user->userName, user->passWord);
    if(strcmp(train.data, "-10") == 0){
        return -1;
    }
    //查询数据库
    char sql[4096] = {0};
    sprintf(sql, "select * from user where userName = '%s';", user->userName);
    int qret = mysql_query(mysql, sql);
    if (qret != 0) {
        printf("qret = %d\n", qret);
        return -1;
    }
    printf("第一处路障通过-无！\n");
    MYSQL_RES *result = mysql_store_result(mysql);
    if(result == NULL){
        printf("mysql find no data\n");
        return -1;
    }
    MYSQL_ROW row = mysql_fetch_row(result);
    printf("第二处路障通过-无！\n");
    //服务端第一次发送，告知客户端，是否注册成功
    if(row == NULL || strcmp(user->userName, row[1]) != 0){
        //不存在，那么直接把 用户信息 添加到数据库的表中
        //用户密码哈希值，则是当场随机生成盐值，进行加密，然后和 盐值 一起存储
        printf("路过特殊路障01-表示用户不存在！\n");
        memset(sql, 0, sizeof(sql));

        // 创建随机盐值，并进行哈希散列加密
        char str[STR_LEN + 1] = {0};
        int i, flag;
        srand(time(NULL));
        for (i = 0; i < STR_LEN; i++) {
            flag = rand() % 3;
            switch (flag) {
            case 0:
                str[i] = rand() % 26 + 'a';
                break;
            case 1:
                str[i] = rand() % 26 + 'A';
                break;
            case 2:
                str[i] = rand() % 10 + '0';
                break;
            }
        }
        printf("中间插入的str = %s\n", str); // 输出生成的随机盐值
        char salt[50] = "$6$";
        strcat(salt, str);
        printf("半成品salt = %s\n", salt);
        char rear[] = "$";
        strcat(salt, rear);
        printf("成品salt =%s\n", salt);

        //哈希散列
        char *hashValue = crypt(user->passWord, salt);
        printf("hashValue = %s\n", hashValue);
        sprintf(sql,
                "insert into user(userName, salt, passWord) values('%s', '%s', "
                "'%s')",
                user->userName, salt, hashValue);
        qret = mysql_query(mysql, sql);
        printf("路过特殊路障02-无！\n");
        if(qret != 0){
            fprintf(stderr, "mysql_query:%s\n", mysql_error(mysql));  
            return -1;
        }
        printf("路过特殊路障03-无！\n");

        memset(&train, 0, sizeof(train));
        char buf[] = "0";
        train.length = sizeof(buf);
        strncpy(train.data, buf, sizeof(buf));
        send(netfd, &train, sizeof(int)+train.length, MSG_NOSIGNAL);
        printf("路过特殊路障04-发送字符串“0”成功！\n");
        printf("train.data = %s\n", train.data);
        mysql_free_result(result);//记得关闭连接
        return 0;
    }else if(strcmp(user->userName, row[1]) == 0){
        //用户名如果存在，服务端回复已存在，注册失败！
        printf("路过特殊路障01-用户存在！\n");
        char buf[] = "1";
        memset(&train, 0, sizeof(train));
        train.length = sizeof(buf);
        memcpy(train.data, buf, train.length);
        send(netfd, &train, sizeof(int)+train.length, MSG_NOSIGNAL);
        printf("路过特殊路障02-发送字符串“1”成功！\n");
        printf("train.data = %s\n",train.data);
        mysql_free_result(result);//记得关闭连接
        return 1;
    }
    else{
        return -1;
    }
}
// 登录函数，只要返回-1，肯定导致登录失败，然后发送登录失败的信息过去
int signIn(int netfd, userInfo_t *user, MYSQL *mysql) {
    // 服务端 登录函数 第二次接收，接收用户名，进行查询，该用户名是否存在
    train_t train;
    memset(&train, 0, sizeof(train));
    recv(netfd, &train.length, sizeof(int), MSG_WAITALL);
    recv(netfd, train.data, train.length, MSG_WAITALL);
    //将得来的用户名，和包含它的用户结构体，一并复制到user里面
    memcpy(user, train.data, train.length);//理论设计 的时候，是一样大的
    printf("userName = %s\npassWord = %s\n", user->userName, user->passWord);

    //进行查询
    char sql[4096] = {0};
    printf("测试是否到mysql_query之前一行\n");
    sprintf(sql, "select * from user where userName = '%s';", user->userName);
    int qret = mysql_query(mysql, sql);
    printf("mysql_query qret = %d\n", qret);
    //得到目标行信息
    MYSQL_RES * result = mysql_store_result(mysql);
    printf("row = %lu, columns = %d\n", mysql_num_rows(result), mysql_num_fields(result));
    MYSQL_ROW row =  mysql_fetch_row(result);
    printf("第一处路障通过-无！\n");
    //if(row == NULL){
    //    fprintf(stderr, "mysql_fetch_row:%s\n", mysql_error(mysql));
    //    return -1;
    //}
    //检查目标行数据，服务端可能第一次发送
    if(row == NULL || strcmp(user->userName, row[1]) != 0){
        //目标行数据没有该用户的话，返回-2，退出！
        printf("特殊路障01-没有该用户名！");

        memset(&train, 0, sizeof(train));
        char buf002[] = "-2"; // 没有buf001，只有buf，因为这里是后面加的
        train.length = sizeof(buf002);
        strncpy(train.data, buf002, train.length);
        send(netfd, &train, sizeof(int)+train.length, MSG_NOSIGNAL);
        mysql_free_result(result);//记得关闭连接
        return -2;
    }
    printf("第二处路障通过-无！\n");

    //服务端可能第一次发送
    //找到用户名对应的盐值，通过哈希散列加密得到密码哈希，
    //和存储的密码哈希进行比较，一样，表示密码正确，否则错误,然后发送过去
    char *hashValue = crypt(user->passWord, row[2]);
    if (strcmp(hashValue, row[3]) == 0) {
        char buf[] = "0";
        printf("特殊路障02-密码哈希值一样，客户端成功登录！\n");

        memset(&train, 0, sizeof(train));
        train.length = sizeof(buf);
        memcpy(train.data, buf, train.length);
        send(netfd, &train, sizeof(int)+train.length, MSG_NOSIGNAL);
        mysql_free_result(result);//记得关闭连接
        return 0;
    }
    else{
        printf("特殊路障03-密码哈希不一样，客户端登录失败！\n");
        mysql_free_result(result); // 记得关闭连接
        return -1;
    }
}
// 处理注册/登录函数的中转函数，狠狠加层
int recvLogIn(int netfd, cmdInfo_t *login, userInfo_t *user, MYSQL *mysql){
    train_t train;//先初始化
    int ret = 0;
    while(1){
        memset(&train, 0, sizeof(train));
        //服务端 注册/登录函数，第一次接收
        int ret1 = recv(netfd, &train.length, sizeof(int), MSG_WAITALL);
        if(ret1 == 0){
            printf("客户端连接断开\n");
            return -4;//由于客户端连接断开导致的错误
        }
        recv(netfd, train.data, train.length, MSG_WAITALL);
        printf("字符train.data = %s\n", train.data);
        int loginCmd = atoi(train.data);
        printf("整型train.data = %d\n", loginCmd);
        //到这一步，已经接收到传来的小火车，准备分流
        switch(loginCmd){
        case SIGN_UP:
            printf("服务端开始调用注册！\n");
            ret = signUp(netfd, user, mysql);//进入注册流程
            if(ret == -1){
                memset(&train, 0, sizeof(train));
                char buf001[] = "-1";

                train.length = sizeof(buf001);
                strncpy(train.data, buf001, train.length);
                send(netfd, &train, sizeof(int)+train.length, MSG_NOSIGNAL);
                printf("客户端注册失败！\n");
                continue;
            }
            else if(ret == 1){
                printf("客户端用户名已存在，注册失败！\n");
                continue;
            }
            printf("用户 %s 成功注册！\n", user->userName);
            break;
        case SIGN_IN:
            printf("准备登录！\n");
            ret = signIn(netfd, user, mysql);//进入登录流程
            if(ret == -1){//只要返回-1，不管什么原因，肯定会导致登陆失败
                          //服务端进行发送
                memset(&train, 0, sizeof(train));
                char buf[] = "-1";
                train.length = sizeof(buf);
                strncpy(train.data, buf, train.length);
                send(netfd, &train, sizeof(int)+train.length, MSG_NOSIGNAL);
                continue;
            }
            else if(ret == -2){
                continue;
            }
            printf("用户 %s 登录成功！\n", user->userName);
            return 0;
        }
    }
    return 0;
}
